
#include <BRender>
#include <BPainter>
#include <BGeometry>
#include <BChangeEvent>

#include "MouseConverter.h"

MouseConverter::MouseConverter(BGeometry* geometry)
{
	_geometry = geometry;
	_display = (BDisplay*)_geometry->texture();
	_widget = _display->widget();
	_pickedObject = 0;
	connect(_display, Signal_Fresh, &MouseConverter::slotDisplayRefresh);
	connect(_widget, Signal_Hide, &MouseConverter::slotWidgetHiden);
}

void MouseConverter::slotDisplayRefresh()
{
	this->fresh();
}
void MouseConverter::slotWidgetHiden()
{
	if(this->viewer()->contain(_widget))
	{
		this->viewer()->removeChild(_widget);
		_widget->show();
	}
}

bool MouseConverter::event(const BEvent& event)
{
	BHandler::event(event);
	if (!_display)
		return false;
	if (event.type() == Event_Change)
	{
		_display->event(event);
	}
	return false;
}

void MouseConverter::paint(BPainter& painter)
{
	if (!_pickedObject)
		return;
	painter.setColor(255, 255, 0);
	painter.drawText(20, 32, _pickedObject->name());

	BCamera* camera = this->camera();
	BVector pos = camera->position();

	BString text("mouse point : ");
	text << _debugPoint.x() << ", " << _debugPoint.y();
	text << "\ncamera position : ";
	text << pos.x() << ", " << pos.y() << ", " << pos.z();

	painter.drawText(20, 56, painter.widget()->width(), 100, text);
}
void MouseConverter::render(BRender& render)
{
	render.setLighting(false);

	render.setColor(255, 0, 0, 255);
	render.setPointSize(5);
	render.setPointSmooth(true);
	render.drawPoint(_debugVector);

	//render.setColor(0, 255, 0, 255);
	//render.drawLine(_debugLine);
}

void MouseConverter::updateEvent(const BEvent& event)
{
	_display->event(event);
}

bool MouseConverter::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	return false;
}
bool MouseConverter::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	return false;
}
bool MouseConverter::mousePressEvent(const BMouseEvent& mouseEvent)
{
	if (_display)
	{
		_mouseEvent.setType(Event_MousePress);
		_mouseEvent.setButton(mouseEvent.button());
		_display->event(_mouseEvent);
		this->viewer()->fresh();
	}
	return false;
}
bool MouseConverter::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	if (_display)
	{
		_mouseEvent.setType(Event_MouseRelease);
		_mouseEvent.setButton(mouseEvent.button());
		_display->event(_mouseEvent);
		this->viewer()->fresh();
	}
	return false;
}
bool MouseConverter::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	if (!_display)
		return false;

	const BPoint& pos = mouseEvent.pos();
	_pickedObject = 0;
	_inside = false;
	BLine line = this->viewer()->line(pos);
	_debugLine = line;
	BScene* scene = this->viewer()->scene();
	BPicker picker(line);
	if (const BPickItem* item = picker.apply(scene))
	{
		BShape* shape = item->shape();
		BMatrix matrix = shape->matrix();
		_debugVector = item->point() * matrix;
		_pickedObject = shape;
		if (shape == _geometry)
		{
			_inside = true;
			BVectorArray* vertices = _geometry->vertices();
			BVector v0 = (*vertices)[0] * matrix;
			BVector v1 = (*vertices)[1] * matrix;
			BVector v2 = (*vertices)[2] * matrix;
			BVector v3 = (*vertices)[3] * matrix;

			BLine topLine(v3, v2);
			BLine leftLine(v3, v0);
			BVector point = item->point() * matrix;
			float quadX = leftLine.distance(point);
			float quadY = topLine.distance(point);
			float quadWidth = (v0 - v1).length();
			float quadHeight = (v0 - v3).length();
			_debugPoint.x() = quadX / quadWidth * _display->width();
			_debugPoint.y() = quadY / quadHeight * _display->height();

			_mouseEvent.setType(Event_MouseMove);
			_mouseEvent.setGlobalPos(_debugPoint);
			_display->event(_mouseEvent);
		}
	}
	this->viewer()->fresh();
	return true;
}

bool MouseConverter::mouseWheelEvent(const BMouseEvent& mouseEvent)
{
	return false;
}
bool MouseConverter::mouseClickEvent(const BMouseEvent& mouseEvent)
{
	if (_display)
	{
		_mouseEvent.setType(Event_MouseClick);
		_display->event(_mouseEvent);
	}
	return false;
}
bool MouseConverter::mouseDoubleClickEvent(const BMouseEvent& mouseEvent)
{
	if (_inside && _display)
	{
		this->viewer()->addChild(_widget);
	}
	return false;
}

bool MouseConverter::dragEnterEvent(const BDragEvent& dragEvent)
{
	return false;
}
bool MouseConverter::dragLeaveEvent(const BDragEvent& dragEvent)
{
	return false;
}
bool MouseConverter::dragMoveEvent(const BDragEvent& dragEvent)
{
	return false;
}
bool MouseConverter::dragDropEvent(const BDragEvent& dragEvent)
{
	return false;
}

